package com.golf.core.game.score;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.golf.core.course.Course;
import com.golf.core.player.Player;

/**
 * A scoreboard to log scores for players on different courses.
 * 
 * @author gareth
 */
public class ScoreBoard
{
    
    /** The collection that holds the player to score mappings. */
    private final Map<Player, Map<String, Score>> scores = new HashMap<Player, Map<String, Score>>();
    
    /** The current course that is being scored. */
    private String currentCourse;
    
    
    /**
     * Create a new scoreboard for a list of players.
     * 
     * @param players The players who will be scored.
     */
    public ScoreBoard(final List<Player> players)
    {
        for (Player player : players)
        {
            scores.put(player, new HashMap<String, Score>());
        }
    }

    
    /**
     * Add a new course to the scoreboard, and set it as current.
     * 
     * @param course The course that will be added.
     */
    public void newCourse(final Course course)
    {
       synchronized (scores)
       {
           for (Entry<Player, Map<String, Score>> entry : scores.entrySet())
           {
               final Map<String, Score> playerScores = entry.getValue();
               playerScores.put(course.name(), new Score(course.name()));
           }    

           currentCourse = course.name();
       }    
    }
    
    
    /**
     * Increment a players score for the current course.
     * 
     * @param player The player to increment for.
     */
    public void chalkShot(final Player player)
    {
        if (currentCourse == null)
        {
            throw new IllegalArgumentException("No course added to scoreboard yet.");
        }
        
        synchronized (scores)
        {
            final Map<String, Score> courseScores = scores.get(player);
            if (courseScores == null)
            {
                throw new IllegalArgumentException("Invalid player.");
            }
            
            final Score courseScore = courseScores.get(currentCourse);
            if (courseScores == null)
            {
                throw new IllegalArgumentException("Player not registered for this course.");
            }
            
            courseScore.increase();
        }
    }
    
    
    /** 
     * Return a map of scores for the given player.
     * 
     * @param player The player to lookup scores against.
     * @return The returned scores.
     */
    public Map<String, Score> getScores(final Player player)
    {
        synchronized (scores)
        {
            return Collections.unmodifiableMap(scores.get(player));
        }    
    }


    /**
     * Get the score for a given player on a given course.
     * 
     * @param player Thhe player to check.
     * @param course The course that the player is on.
     * 
     * @return The stroke count for the course.
     */
    public int getCourseScore(final Player player, final Course course)
    {
        synchronized (scores)
        {
            return scores.get(player).get(course.name()).getScore();
        }    
    }

}